#pragma once

// rands
#define RAND_FLOAT(min, max) (((rand()/(float)RAND_MAX)*((max)-(min)))+(min))
#define RAND_DOUBLE(min, max) (((rand()/(double)RAND_MAX)*((max)-(min)))+(min))
#define RAND_INT(min, max) (rand() % (max - min + 1) + min)
#define RAND_D3DXVECTOR2(min, max) (D3DXVECTOR2(RAND_FLOAT(min.x, max.x), RAND_FLOAT(min.y, max.y)))
#define RAND_D3DXVECTOR3(min, max) (D3DXVECTOR3(RAND_FLOAT(min.x, max.x), RAND_FLOAT(min.y, max.y), RAND_FLOAT(min.z, max.z)))
#define RAND_U32COLOR() (rand() % 0x01000000 + 0xFF000000)
//#define RAND_COLOR(min, max) (RAND_INT(min, max))


#define U32COLOR_ARGB(a, r, g, b) ((U32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
// TODO rest of them

// U32 Color - gets values
#define U32COLOR_GET_A(color) (color >> 24)
#define U32COLOR_GET_R(color) ((color >> 16) ^ ((color >> 24) << 8))
#define U32COLOR_GET_G(color) ((color >> 8) ^ ((color >> 16) << 8))
#define U32COLOR_GET_B(color) ((color) ^ ((color >> 8) << 8))

// U32 color - sets values
#define U32COLOR_SET_A(color, a) (/*color = */((a & 0xff) << 24) | (color ^ ((color >> 24) << 24)))
#define U32COLOR_SET_R(color, r) (/*color = */((r & 0xff) << 16) | (color ^ ((color >> 16) << 16) ^ ((color >> 24) << 24)))
#define U32COLOR_SET_G(color, g) (/*color = */((g & 0xff) << 8) | (color ^ ((color >> 8) << 8) ^ ((color >> 16) << 16)))
#define U32COLOR_SET_B(color, b) (/*color = */((b & 0xff)) | (color ^ ((color >> 8) << 8)))

// D3DXCOLOR conversions
#define D3DXCOLOR_TO_D3DCOLOR(color) (D3DCOLOR_ARGB((byte)(color.a * 255.0f), (byte)(color.r * 255.0f), (byte)(color.g * 255.0f), (byte)(color.b * 255.0f)))
#define D3DCOLOR_TO_D3DXCOLOR(color) (D3DXCOLOR(D3DCOLOR_GET_R(color) / 255.0f, D3DCOLOR_GET_G(color) / 255.0f, D3DCOLOR_GET_B(color) / 255.0f, D3DCOLOR_GET_A(color) / 255.0f))

// Float to DWORD
#define FTODW(var) (*((DWORD*)&var))

// epsilon
#define EPSILON (0.0001f)

// bits
#define BIT_ON(var, bit) (var |= (1 << bit))
#define BITS_ON(var, bits) (var |= bits)
#define BIT_TOGGLE(var, bit) (var ^= (1 << bit))
#define BITS_TOGGLE(var, bits) (var ^= bits)
#define BIT_OFF(var, bit) (var &= ~(1 << bit))
#define BITS_OFF(var, bits) (var &= ~bits)
#define BIT_TEST_ON(var, bit) (var & (1 << bit))
#define BIT_TEST_OFF(var, bit) (!(var & (1 << bit)))
#define BITS_TEST_ON(var, bits) ((var & bits) == bits)
#define BITS_TEST_OFF(var, bits) ((var & bits) != bits)
#define BITS_FLIP_ALL(var) (var = ~var)
#define BITS_SET(var, val, place) (var = (var | (val << place)) & (~(val << place)))
#define BITS_SET_ALL_ON(var) (var = -1)
#define BITS_SET_ALL_OFF(var) (var = 0)
#define BITS_RESET(var) (BITS_SET_ALL_OFF(var))

// memory releases
#define	SAFE_RELEASE(var) if (p) { if(p->Release()) p = NULL; } }
#define	SAFE_RELEASE_INPUT(var) if (var) { var->Unacquire(); var->Release(); var = NULL; }
#define SAFE_DELETE(var) if (var) { delete var; var = NULL; }
#define SAFE_DELETE_ARRAY(var) if (var) { delete[] var; var = NULL; }
#define SAFE_FREE(var) if (var) { free(var); var = NULL; }

// inlines
#define INLINE _inline
#define FORCEINLINE __forceinline

// alignment
#define ALIGN16 __declspec(align(16))

// pi
#define PI ((double)3.1415926535897932384626433832795)
#define PI_F ((float)3.141592654f)

// handles
#define HANDLE_NULL NULL;

// vectors
#define VECTOR2_ZERO 0.0f, 0.0f
#define VECTOR3_ZERO 0.0f, 0.0f, 0.0f

// matrixes
#define VAR_TO_VEC3(var) (*(D3DXVECTOR3*)(&var))
#define MATRIX_XAXIS(var) (*(D3DXVECTOR3*)&(var)._11)
#define MATRIX_YAXIS(var) (*(D3DXVECTOR3*)&(var)._21)
#define MATRIX_ZAXIS(var) (*(D3DXVECTOR3*)&(var)._31)
#define MATRIX_POSITION(var) (*(D3DXVECTOR3*)&(var)._41)

// singletons
#define DECLARE_SINGLETON_H(type) extern type* g_##type##Instance
#define DECLARE_SINGLETON_CPP(type) type* g_##type##Instance = type::GetInstance()
#define SINGLETON_CLASS_FUNCTIONS(type) type##(void); \
	type##(##type##&); \
	~##type##(void); \
	type##& operator=(##type##&); 

// variable types
typedef unsigned __int8 U8;
typedef unsigned __int16 U16;
typedef unsigned __int32 U32;
typedef unsigned __int64 U64;
typedef signed __int8 S8;
typedef signed __int16 S16;
typedef signed __int32 S32;
typedef signed __int64 S64;
typedef unsigned long lp; // TODO change to uppercase somehow

#pragma warning(disable : 4995)
#pragma warning(disable : 4996)
#pragma warning(disable : 4482)
#pragma warning(disable : 4201)
#pragma warning(disable : 4324) // padding for classes
#pragma intrinsic(sin, cos, tan, asin, acos, atan)
#pragma intrinsic(sqrt, pow, log, abs)

#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768

//#define NO_POPUPS